from logging.handlers import TimedRotatingFileHandler
from typing import TypedDict, Literal
from typing_extensions import Annotated
from functools import lru_cache
from config import get_settings

import logging
import os


__all__ = [
    "create_logger",
    "InputLoggerDict",
    "get_data_logger",
    "get_server_logger",
    "get_check_logger",
]

settings = get_settings()


class InputLoggerDict(TypedDict):
    logger_name: Annotated[str, "日志器名字"]
    level: int = logging.INFO
    file_name: Annotated[str, "日志文件名"] = "data_log.log"
    backupCount: Annotated[int, "备份文件数量"] = 24
    enable_file: Annotated[bool, "保存到文件"] = True
    enable_console: Annotated[bool, "控制台输出"] = True


def create_logger(args: InputLoggerDict) -> logging.Logger:

    logger = logging.getLogger(args["logger_name"])
    logger.setLevel(args["level"])
    data_log_makedir = os.path.join(settings.BASE_DIR, "logs")
    filename_makedir = os.path.join(data_log_makedir, args["logger_name"])

    # 创建文件夹
    if not os.path.exists(data_log_makedir):
        os.makedirs(data_log_makedir)
    if not os.path.exists(filename_makedir):
        os.makedirs(filename_makedir)

    # 如果是Error级别显示错误代码的位置
    if args["level"] == logging.ERROR:
        fmt = '> [{module}][{levelname}][{asctime}]({pathname}:{lineno}): {message}'
    else:
        fmt = '> [{module}][{levelname}][{asctime}]: {message}'

    formatter = logging.Formatter(
        fmt=fmt,
        style="{"
    )

    # 1. 文件处理器
    if args["enable_file"]:
        fileHandler: TimedRotatingFileHandler = TimedRotatingFileHandler(
            filename=os.path.join(filename_makedir, args["file_name"]),
            when='H',
            interval=1,
            backupCount=args["backupCount"],
        )
        fileHandler.suffix = "%Y%m%d%H"
        fileHandler.setLevel(args["level"])
        fileHandler.setFormatter(formatter)
        logger.addHandler(fileHandler)

    # 2. 控制台处理器
    if args["enable_console"]:
        consoleHandler = logging.StreamHandler()
        consoleHandler.setLevel(args["level"])
        consoleHandler.setFormatter(formatter)
        logger.addHandler(consoleHandler)

    return logger


@lru_cache
def get_error_logger() -> logging.Logger:
    return create_logger(InputLoggerDict(
        logger_name="error_logger",
        level=logging.ERROR,
        file_name="error_log.log",
        backupCount=12,
        enable_file=True,
        enable_console=True))


@lru_cache
def get_data_logger() -> logging.Logger:
    return create_logger(InputLoggerDict(
        logger_name="data_logger",
        level=logging.INFO,
        file_name="data_log.log",
        backupCount=72,
        enable_file=True,
        enable_console=True))


@lru_cache
def get_server_logger() -> logging.Logger:
    return create_logger(InputLoggerDict(
        logger_name="server_logger",
        level=logging.INFO,
        file_name="server_log.log",
        backupCount=12,
        enable_file=True,
        enable_console=True))


@lru_cache
def get_check_logger() -> logging.Logger:
    return create_logger(InputLoggerDict(
        logger_name="check_logger",
        level=logging.INFO,
        file_name="check_log.log",
        backupCount=12,
        enable_file=True,
        enable_console=True))


@lru_cache
def get_websocket_logger() -> logging.Logger:
    return create_logger(InputLoggerDict(
        logger_name="websocket_logger",
        level=logging.INFO,
        file_name="websocket_log.log",
        backupCount=12,
        enable_file=True,
        enable_console=True))
